/*  
  -- The Lime II Project -- 

  A tuplespaces-based middleware for coordinating agents and mobile hosts.
  Copyright (C) 2005.
  Gian Pietro Picco, Amy L. Murphy, Lorenzo Bellini.

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  Lesser General Public License for more details.

  You should have received this copy of the GNU Lesser General Public
  License along with this library; if not, write to the Free Software
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 
*/

package lime2.trackerca;
import lime2.ca.EngMsg;
import lime2.*;
import java.io.*;
import java.net.*;

/**
 * A "receiver" of remote multicast messages. It listens "on" a UDP socket, receives remote ops and enqueues them.
 * Please note that in multicast communication we have to discard datagrams that are looped-back: we check the sender
 * port and address of the datagram; we don't want to go through deserialization (overhead of deserializing the looped
 * back messages). The convention is that datagrams are sent using the unicast port number of the host. 
 * 
 * @author Gian Pietro Picco
 * @author Amy Murphy
 * @author Lorenzo Bellini 
 */

class TrackerPlainMulticastReceiver extends Thread
{
 // private data members	
 private DatagramSocket dsock, ssock;
 private int portcheck;
 private boolean shutdown; 
 
 /**
  * Constructor method. 
  * 
  * @param dsock datagram socket to use for listening
  * @param ssock datagram socket used for sending
  * @param portcheck in multicast communication we have to discard looped-back datagrams; sender datagram port for
  *        this host; <code>-1</code> disables the check 
  */
 TrackerPlainMulticastReceiver(DatagramSocket dsock, DatagramSocket ssock, int portcheck)
 {
  super();
  this.dsock = dsock;
  this.ssock = ssock;
  this.portcheck = portcheck;
  this.shutdown = false;
 }
	
/**
 * Run method. 
 */
 public void run()
 {
  // initializations
  byte[] buffer = new byte[LimeConstants.UDP_BUFFER_SIZE];
  InetAddress here = LimeServer.getServer().getUnicastAddress();
  // loop
  while (!shutdown) 
  {
   try 
   {	
    DatagramPacket dp = new DatagramPacket(buffer, buffer.length);
    dsock.receive(dp);
    if (portcheck == -1 || dp.getPort() != portcheck || !here.equals(dp.getAddress())) 
    // discards its own looped-back datagrams 
    {
     Object o = Serializer.deserialize(dp.getData());
     if (!(o instanceof EngMsg))
     {
    	 TrackerPlainCA.queue.add(o); 
     }
    } 
   }
   catch (IOException ioe) { ioe.printStackTrace(); } // just prints stack trace: "robust" server 
  } 
  // end loop
  dsock.close();
  ssock.close(); // .. when we stop multicast communication, we have to close also the datagram sender socket !!
  ssock = null;  // .. from now on trying to send a multicast message will result in a TOTAL failure
 }

 /**
  * Shuts the receiver down.
  */
 void shutdown()
 {
  shutdown = true;	
 }
  
} 